package com.beiding.jsonanalyzer.analyze.func.openfunc;

import com.beiding.jsonanalyzer.analyze.Undefind;
import com.beiding.jsonanalyzer.analyze.func.FuncBase;
import com.beiding.jsonanalyzer.analyze.func.FuncFactory;
import com.beiding.jsonanalyzer.analyze.func.base.FuncFactoryAdaptor;
import com.beiding.jsonanalyzer.analyze.query.ComparatorResult;
import com.beiding.jsonanalyzer.analyze.query.SelfQueryGrammar;
import com.beiding.jsonanalyzer.flow.ValueNode;
import com.beiding.jsonanalyzer.utils.TextUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author 丁常磊
 * @date 2022/5/9 15:44
 */

public class Case extends FuncFactoryAdaptor<Case.F> {

    public static Case of(Object caseKey) {

        Case c = new Case();

        FuncFactory caseFactory = FuncUtils.ensureFuncFactory(caseKey);
        FuncFactory nullFactory = FuncUtils.ensureFuncFactory(Undefind.i);

        c.addForFunc(f -> {
            f.defaultKey = nullFactory.createInstance();
            f.caseKey = caseFactory.createInstance();
            f.checkAggs.add(f.caseKey);
            f.checkAggs.add(f.defaultKey);

        });

        return c;
    }


    public CheckWhen when(FuncFactory<FuncBase<ComparatorResult>> whenQuery) {
        CheckWhen checkWhen = new CheckWhen();
        checkWhen.whenFactory = whenQuery;
        return checkWhen;
    }

    public CheckWhen when(Object whenValue) {
        CheckWhen checkWhen = new CheckWhen();
        checkWhen.whenFactory = new SelfQueryGrammar(){}.eq(whenValue).getQueryBuilder();
        return checkWhen;
    }

    public FuncFactory<Case.F> Default(Object key) {
        return default_(key);
    }

    public FuncFactory<Case.F> default_(Object key) {

        FuncFactory valueFactory = FuncUtils.ensureFuncFactory(key);

        addForFunc(f -> {
            f.checkAggs.remove(f.defaultKey);
            f.defaultKey = valueFactory.createInstance();
            f.checkAggs.add(f.defaultKey);
        });


        return this;
    }


    @Override
    protected F newInstance() {
        return new F();
    }

    private static class CasePair {
        FuncBase<ComparatorResult> query;
        FuncBase key;
    }


    static class F implements FuncBase {
        /**
         * 此模式中caseKey一定不为空
         */
        private FuncBase caseKey;

        /**
         * 默认返回 undefined
         */
        private FuncBase defaultKey;

        private List<CasePair> casePairs = new ArrayList<>();

        /**
         * 需要检查聚合的函数列表
         */
        private List<FuncBase> checkAggs = new ArrayList<>();

        @Override
        public boolean checkAgg() {
            for (FuncBase fb : checkAggs) {
                if (fb.checkAgg()) {
                    return true;
                }
            }
            return false;
        }


        @Override
        public Object executeOne(ValueNode valueNode) {

            Object o = caseKey.executeOne(valueNode);

            ValueNode node = new ValueNode();
            node.set(o);

            for (CasePair casePair : casePairs) {
                ComparatorResult o1 = casePair.query.executeOne(node);
                if (o1 == ComparatorResult.TRUE) {
                    return casePair.key.executeOne(valueNode);
                }
            }

            //返回默认返回
            return defaultKey.executeOne(valueNode);

        }

        @Override
        public void pugAgg(ValueNode valueNode) {
            for (FuncBase checkAgg : checkAggs) {
                checkAgg.pugAgg(valueNode);
            }
        }

        @Override
        public void resetAgg() {
            for (FuncBase checkAgg : checkAggs) {
                checkAgg.resetAgg();
            }
        }

        @Override
        public Object aggGet() {

            Object o = caseKey.aggGet();

            ValueNode node = new ValueNode();
            node.set(o);
            for (CasePair casePair : casePairs) {
                ComparatorResult o1 = casePair.query.aggGet();
                if (o1 == ComparatorResult.TRUE) {
                    return casePair.key.aggGet();
                }
            }


            //如果都没有结果

            //返回默认返回
            return defaultKey.aggGet();
        }


        @Override
        public String toString() {
            StringBuilder builder = new StringBuilder();
            builder.append("case ").append(caseKey).append("\n");
            for (Case.CasePair casePair : casePairs) {
                builder.append("\twhen ").append("\n").append(TextUtils.addFormat(casePair.query, "\t\t")).append("\n\t then \n").append(TextUtils.addFormat(casePair.key, "\t\t")).append("\n");
            }
            builder.append("\tdefault ").append(defaultKey).append("\nend case");
            return builder.toString();
        }

    }


    public class CheckWhen extends FuncFactoryAdaptor<Case.F> {

        private FuncFactory<FuncBase<ComparatorResult>> whenFactory;

        public Case then(Object valueKey) {
            FuncFactory valueFactory = FuncUtils.ensureFuncFactory(valueKey);
            Case.this.addForFunc(f -> {
                CasePair casePair = new CasePair();
                whenFactory.createInstance();
                casePair.key = valueFactory.createInstance();
                f.casePairs.add(casePair);
                f.checkAggs.add(casePair.key);
                f.checkAggs.add(casePair.query);
            });
            return Case.this;
        }

        @Override
        protected F newInstance() {
            return Case.this.newInstance();
        }
    }


}
